package com.vcaresolution.logistic.service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.vcaresolution.logistic.form.LoginForm;
import com.vcaresolution.logistic.form.UserForm;
import com.vcaresolution.logistic.pojo.Branch;
import com.vcaresolution.logistic.pojo.Company;
import com.vcaresolution.logistic.pojo.Department;
import com.vcaresolution.logistic.pojo.Securityquestion;
import com.vcaresolution.logistic.pojo.User;
import com.vcaresolution.logistic.pojo.Userbranch;
import com.vcaresolution.logistic.pojo.Userdepartment;
import com.vcaresolution.logistic.pojo.Usergroup;
import com.vcaresolution.logistic.to.UserProfileTO;
import com.vcaresolution.logistic.util.ApplicationConstants;
import com.vcaresolution.util.Utils;

/**
 * <code>UserServiceImpl</code> is an implementation of UserService. It is used to track 
 * all User related activities. This includes login, registration etc.
 * 
 * @author Snehal Shah
 * @version 1.0
 * @since ShipSoft 1.0
 * @see UserService
 */
@Service
public class UserServiceImpl extends BaseService implements UserService{

	private User populateUserPojo(UserForm userForm){
		User user = new User();
		BeanUtils.copyProperties(userForm, user);
		
		return user;
	}
	
	@Override
	@Transactional
	public UserProfileTO login(LoginForm loginForm) {
		final User user = getDaoFactory().getUserDAO().login(loginForm);
		
		UserProfileTO userProfileTO = null;
		if( user != null ){
			userProfileTO = new UserProfileTO();
			userProfileTO.setUserid(user.getUserid());
			
			userProfileTO.setFirstname(user.getFirstname());
			userProfileTO.setLastname(user.getLastname());
			userProfileTO.setMiddlename(user.getMiddlename());
			
			userProfileTO.setLastlogindate(user.getLastlogindate());
			
			userProfileTO.setCompanyId(user.getCompany().getCompanyid());
			
			/*******************************************/
			Set<Userbranch> userbranches = user.getUserbranches();
			
			/**#editedByVishal*/
			if(!userbranches.isEmpty())
			{
				Userbranch userBranch = userbranches.iterator().next();	
				System.out.println("Branch Code is :: "+userBranch.getBranch().getBranchcode());
				userProfileTO.setBranchCode(userBranch.getBranch().getBranchcode());
			}
			
			/*Userbranch userBranch = userbranches.iterator().next();	
			System.out.println("Branch Code is :: "+userBranch.getBranch().getBranchcode());
			userProfileTO.setBranchCode(userBranch.getBranch().getBranchcode());*/
			/*******************************************/
			userProfileTO.setUserGroupId(user.getUsergroup().getUsergroupid());
			
			//Security Token Code - Start
			userProfileTO.setUserTokenValues(getDaoFactory().getUserDAO().populateUserTokenValues(user.getUsergroup().getUsergroupid()));
			//Security Token Code - End
		}
		
		return userProfileTO; 
	}

	@Override
	@Transactional
	public List<UserProfileTO> findByAll() {

		List<User> userList = getDaoFactory().getUtilityDAO().findByAll(User.class);
		
		List<UserProfileTO> userFormList = new ArrayList<UserProfileTO>();
		
		if( userList != null && !userList.isEmpty() ){
			UserProfileTO userForm = null;
			for(User user : userList){
				userForm = new UserProfileTO();
				
				BeanUtils.copyProperties(user, userForm);
				userFormList.add(userForm);
			}
		}
		
		return userFormList;
	}

	@Override
	@Transactional
	public void add(UserForm userForm) {

		/**#editedByVishal*/
		User user = populateUserPojo(userForm);
		
		Company company = (Company) getDaoFactory().getUtilityDAO().findById(Company.class, userForm.getCompanyId());
		user.setCompany(company);
		
		
		Usergroup usergroup = (Usergroup) getDaoFactory().getUtilityDAO().findById(Usergroup.class, userForm.getUserGroupId());
		user.setUsergroup(usergroup);
		
		Securityquestion question = (Securityquestion) getDaoFactory().getUtilityDAO().findById(Securityquestion.class, userForm.getSecurityQuestionId());
		user.setSecurityquestion(question);
		
		user.setCreationdate(Utils.getCurrentDate());
//		user.setAuditdate(Utils.getCurrentDate());
		
		//Setting Default Status as Active 
		user.setIsactive(ApplicationConstants.ACTIVE_STATUS);
		
//		getDaoFactory().getUtilityDAO().add(user);
		Serializable generatedId =getDaoFactory().getUtilityDAO().insert(user);

		addAssociatedBranches(generatedId, userForm.getBranchId());
		addAssociatedDepartments(generatedId, userForm.getDepartmentId());
	}

	@Override
	@Transactional
	public UserProfileTO findById(Serializable userID) {
		User user = (User) getDaoFactory().getUtilityDAO().findById(User.class,userID);
		
		UserProfileTO userProfileTO = new UserProfileTO();
		BeanUtils.copyProperties(user, userProfileTO);
		
		userProfileTO.setSecurityQuestionId(user.getSecurityquestion().getSqid());
		userProfileTO.setCompanyId(user.getCompany().getCompanyid());
		userProfileTO.setUserGroupId(user.getUsergroup().getUsergroupid());
		Set<Integer> branches = new LinkedHashSet<Integer>();
		Set<Integer> departments = new LinkedHashSet<Integer>();
		
		for(Userbranch userBranch:user.getUserbranches())
		{
			branches.add(userBranch.getBranch().getBranchid());
		}
		
		for(Userdepartment userDepartment:user.getUserdepartments())
		{
			departments.add(userDepartment.getDepartment().getDepartmentid());
		}
		
		userProfileTO.setBranchId(branches);
		userProfileTO.setDepartmentId(departments);
		
		return userProfileTO;
	}

	@Override
	@Transactional
	public void update(UserForm userForm) {

		User user = populateUserPojo(userForm);
		
		Company company = (Company) getDaoFactory().getUtilityDAO().findById(Company.class, userForm.getCompanyId());
		user.setCompany(company);
		
		Usergroup usergroup = (Usergroup) getDaoFactory().getUtilityDAO().findById(Usergroup.class, userForm.getUserGroupId());
		user.setUsergroup(usergroup);
		
		Securityquestion question = (Securityquestion) getDaoFactory().getUtilityDAO().findById(Securityquestion.class, userForm.getSecurityQuestionId());
		user.setSecurityquestion(question);
		
		user.setCreationdate(Utils.getCurrentDate());
		
		getDaoFactory().getUtilityDAO().update(user);
		
		deleteAssociatedBranches(user.getUserid());
		addAssociatedBranches(user.getUserid(), userForm.getBranchId());
		
		deleteAssociatedDepartments(user.getUserid());
		addAssociatedDepartments(user.getUserid(), userForm.getDepartmentId());
		
	}

	@Override
	public void addAssociatedBranches(Serializable userId, Set<Integer> branchId) 
	{
		try
		{
			Iterator<Integer> branchIdIterator = branchId.iterator();
			Branch branch;
			Userbranch userBranch;
			User addedUser = (User) getDaoFactory().getUtilityDAO().findById(User.class, userId);
			while (branchIdIterator.hasNext()) 
			{
				userBranch = new Userbranch();
				branch = (Branch) getDaoFactory().getUtilityDAO().findById(Branch.class, branchIdIterator.next());
				userBranch.setUser(addedUser);
				userBranch.setBranch(branch);
				getDaoFactory().getUtilityDAO().add(userBranch);
			}	
		}
		catch (Exception e) 
		{
			e.printStackTrace();
		}
	}

	@Override
	public void addAssociatedDepartments(Serializable userId,Set<Integer> departmentId) 
	{
		try
		{
			Iterator<Integer> departmentIdIterator = departmentId.iterator();
			Department department;
			Userdepartment userDepartment;
			User addedUser = (User) getDaoFactory().getUtilityDAO().findById(User.class, userId);
			while (departmentIdIterator.hasNext()) 
			{
				userDepartment = new Userdepartment();
				department = (Department) getDaoFactory().getUtilityDAO().findById(Department.class, departmentIdIterator.next());
				userDepartment.setUser(addedUser);
				userDepartment.setDepartment(department);
				getDaoFactory().getUtilityDAO().add(userDepartment);
			}			
		}
		catch (Exception e) 
		{
			e.printStackTrace();
		}
	}

	@Override
	public void deleteAssociatedBranches(Serializable userId) 
	{
		try
		{
			for(Userbranch userBranch:getDaoFactory().getUserDAO().getAssociatedBranches(userId))
			{
				getDaoFactory().getUtilityDAO().delete(userBranch);
			}
		}
		catch (Exception e) 
		{
			e.printStackTrace();
		}
	}

	@Override
	public void deleteAssociatedDepartments(Serializable userId) 
	{
		try
		{
			for(Userdepartment userDepartment:getDaoFactory().getUserDAO().getAssociatedDepartments(userId))
			{
				getDaoFactory().getUtilityDAO().delete(userDepartment);
			}
		}
		catch (Exception e) 
		{
			e.printStackTrace();
		}		
	}

}
